home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / aecdev.aedaemon / aedaemonppcstuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  8.6 KB  |  236 lines

  1. /*
  2.     File:        AEDaemonPPCStuff.c
  3.  
  4.     Contains:    This file contains all the PPC stuff for the AEDeamon.  It reads the AppleEvent
  5.                 data from the PPC channel, puts it in an AEDesc, and fires it for AESend.
  6.                 That's all it does.  But _not_ all it could do.  If the sender wanted a reply,
  7.                 the Deamon could send the reply back through the same channel the event came through.
  8.                 This sample does the minimum, but you can expand it reasonably easily to 
  9.                 give full AppleEvent support to any DA/INIT/CDEV/DRIVER you want.
  10.  
  11.     Written by: C.K. Haun    
  12.  
  13.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  14.  
  15.                 You may incorporate this Apple sample source code into your program(s) without
  16.                 restriction. This Apple sample source code has been provided "AS IS" and the
  17.                 responsibility for its operation is yours. You are not permitted to redistribute
  18.                 this Apple sample source code as "Apple sample source code" after having made
  19.                 changes. If you're going to re-distribute the source, we require that you make
  20.                 it clear in the source that the code was descended from Apple sample source
  21.                 code, but that you've made changes.
  22.  
  23.     Change History (most recent first):
  24.                 7/20/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  25.                 
  26.  
  27. */
  28. #include <TextUtils.h>
  29. #include "AEDaemon.h"
  30.  
  31.  
  32. Handle dataHandle;
  33. OSType gTypeTag;
  34. Boolean gMore;
  35. PPCPortRec ourPort;
  36. PPCPortRefNum ourPortID;
  37. MyPPCRecPtrDeamon ourPPCPtr;
  38. PPCPortRec myPortName;
  39. LocationNameRec myLoc;
  40. Ptr readBuffer;
  41. Handle eventData;
  42. #define kGenStrings 128
  43. #define kPortName 132
  44. extern Boolean gReadPending;
  45. extern unsigned long gMySleep;
  46.  
  47. /* InformTheWorld opens our PPC port, and posts a PPCInform so other folks */
  48. /* can connect to us */
  49. Boolean InformTheWorld(void)
  50. {
  51.     Boolean result = false;
  52.     
  53.     OSErr myErr = noErr;
  54.     PPCOpenPBPtr localPtr;
  55.     localPtr = (PPCOpenPBPtr)ourPPCPtr;                     /* makes things more readable */
  56.     /* get a buffer to read stuff into */
  57.     /* first get a port, if we don't already have one */
  58.     if (ourPortID == nil) {
  59.         myErr = OpenAPort((PPCOpenPBPtr)ourPPCPtr);
  60.         if (myErr)
  61.             return(false);                                  /* we failed, die */
  62.         
  63.         ourPortID = localPtr->portRefNum;
  64.     }
  65.     DoInform((PPCInformPBPtr)ourPPCPtr);
  66.     
  67.     return(result);
  68. }
  69.  
  70. /* OpenAPort, uhhh, opens a port.  Opens our PPC port for others */
  71. /* to talk to us through */
  72. OSErr OpenAPort(PPCOpenPBPtr myPort)
  73. {
  74.     myPortName.nameScript = 0;
  75.     GetIndString(myPortName.name,kGenStrings,kPortName);
  76.     myPortName.portKindSelector = ppcByCreatorAndType;
  77.     myPortName.u.port.portCreator = 'MOOB';
  78.     myPortName.u.port.portType = 'APPL';
  79.     myPort->ioCompletion = NewPPCCompProc(OpenComplete);
  80.     
  81.     myPort->serviceType = ppcServiceRealTime;               /* only valid one under 7.0 */
  82.     myPort->resFlag = 0;
  83.     myPort->portName = &myPortName;
  84.     myPort->locationName = &myLoc;
  85.     myPort->networkVisible = false;                         /* NO, I don't want others using this service */
  86.     myLoc.locationKindSelector = ppcNoLocation;
  87.     
  88.     /* open syncrnouls */
  89.     return(PPCOpen(myPort, true));
  90.     
  91. }
  92.  
  93. /* PPCOpenPort */
  94.  
  95. /* DoInform posts a PPCInform, telling the world that we are ready to */
  96. /* accept data through our PPC channel */
  97. Boolean DoInform(PPCInformPBPtr p)
  98. {
  99.     
  100.     p->ioCompletion = NewPPCCompProc(InformComplete);
  101.     /* port reference number is already set in the Parameter Block */
  102.     /* most of this junk is already set */
  103.     p->portName = nil;
  104.     p->locationName = nil;
  105.     p->userName = nil;
  106.     p->autoAccept = true;   /* if true session will be accepted automatically */
  107.     /* instead of having to go through a PPCAccept.  I'm doing this primarly */
  108.     /* because this deamon is not network visible, so I don't thing anyone */
  109.     /* will be playing hijinks on us.  */
  110.     if (PPCInform(p, true) != noErr) {       
  111.         return false;
  112.     } else
  113.         return true;
  114. }
  115.  
  116. /* DoInform */
  117.  
  118. /* CloseOffTheWorld shuts things down when this app quits */
  119. void CloseOffTheWorld(void)
  120. {
  121.     PPCClosePBPtr closeRec = (PPCClosePBPtr)NewPtrClear(sizeof(PPCClosePBRec));
  122.     closeRec->ioCompletion = nil;
  123.     closeRec->ioResult = 0;
  124.     closeRec->portRefNum = ourPortID;
  125.     PPCClose(closeRec, false);
  126.     DisposePtr((Ptr)closeRec);
  127.     
  128.     
  129. }
  130.  
  131. /* I could post the PPC inform from here, but I decided not to in this case.  */
  132. /* Why?  I'm not sure. */
  133. void OpenComplete(PPCInformPBPtr p)
  134. {
  135. #pragma unused (p)
  136.     /* do nothing */
  137.     
  138. }
  139.  
  140. /* When this InformCompletion routine is hit, that means that someone has */
  141. /* invoked a PPCStart on our port.  Since we automatically accepted it, we */
  142. /* will begin reading from here.  If we wanted to authenticate, we'd do a PPCAccept */
  143. /* here (if we wanted to accept) and then start the read from the */
  144. /* PPCAccept completion routine. */
  145. void InformComplete(PPCReadPBPtr p)
  146. {
  147.     /* Start reading Bucky */
  148.     
  149.     p->ioCompletion = NewPPCCompProc(ReadComplete);
  150.     p->bufferPtr = readBuffer;
  151.     p->bufferLength = kOneK;
  152.     gMySleep = 1; /* bump the sleep time down so we can start processing faster */
  153.     /* so we can process the data after it's read */
  154.     /* since we won't go through WaitNextEvent and see the completion flag unless */
  155.     /* we bump the sleep time down a bit */
  156.     PPCRead((PPCReadPBPtr)p, true);
  157. }
  158.  
  159. /* When we hit this completion routine, it means one of two things; */
  160. /* 1) We are all done reading, and we are ready to send the event */
  161. /* or */
  162. /* 2) We've filled our PPC buffer (rememeber, it was only one K ) */
  163. /* and we need to swap that data to a safe place and read again */
  164. void ReadComplete(PPCReadPBPtr p)
  165. {
  166.     /* read completeed, deal with it */
  167.     gReadPending = true;
  168.     gMore = p->more;
  169.     gTypeTag = p->blockType;
  170.     gMySleep = 0;
  171. }
  172.  
  173. /* this processes the result of the last async read, and re-reads if */
  174. /* theres more data to get */
  175. /* It also checks to see if this is data we understand. In this case, MAVT type */
  176. /* data (which means My AppleeVenT), I set this type in the PPCWrite block */
  177. /* elsewhere.  If you don't do this, bad things will happen when you try */
  178. /* and do an AESend on data someone else sent */
  179. void CollectLastData(void)
  180. {
  181.     unsigned long currentSize;
  182.     AppleEvent theEvent;
  183.     PPCReadPBPtr localPtr = (PPCReadPBPtr)ourPPCPtr;
  184.     if (gMore) {
  185.         /* we need to move the current data into another buffer, and then read again */
  186.         currentSize = GetHandleSize(dataHandle);
  187.         SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  188.         HLock(dataHandle);
  189.         BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  190.         HUnlock(dataHandle);
  191.         localPtr->ioCompletion = NewPPCCompProc(ReadComplete);
  192.         localPtr->bufferPtr = readBuffer;
  193.         localPtr->bufferLength = kOneK;
  194.         /* read more */
  195.         PPCRead((PPCReadPBPtr)localPtr, true);
  196.         
  197.     } else {
  198.         /* now we need to send the thing.  So send it, then re-post the inform */
  199.         /* there's no more, but we need to move what we have */
  200.         /* same as before */
  201.         if (gTypeTag == kMyTypeOfData) {
  202.             currentSize = GetHandleSize(dataHandle);
  203.             SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  204.             HLock(dataHandle);
  205.             BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  206.             HUnlock(dataHandle);
  207.             
  208.             PPCEnd((PPCEndPBPtr)localPtr, false);
  209.             
  210.             gReadPending = false;
  211.             gMySleep = 200;                                 /* back to sleep */
  212.             /* now send the event we've so laboriously xfered */
  213.             /* you'll notice here that I am setting the descriptor type */
  214.             /* to 'aevt' and using some default interaction, reply, and */
  215.             /* timeout values.  To be more flexible, you should pass all these paramters */
  216.             /* as a 'header' block through PPC, see the Read Me file for more details */
  217.             /* I am doing this here for simpliciites sake */
  218.             theEvent.descriptorType = kCoreEventClass;
  219.             theEvent.dataHandle = dataHandle;
  220.             AESend(&theEvent, nil, kAECanInteract + kAENoReply + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
  221.                    nil, nil);
  222.             /* so we just sent the event. Normally, you'd call AEDisposeDesc on this thing, */
  223.             /* but in this case since it's our handle made by us, I'll just set it's size */
  224.             /* back to zero */
  225.         } else {
  226.             /* it was not my data type, so end the session */
  227.             PPCEnd((PPCEndPBPtr)localPtr, false);
  228.         }
  229.         SetHandleSize(dataHandle, 0);
  230.         /* Now we re-inform, we're ready for another message */
  231.         InformTheWorld();
  232.     }
  233. }
  234.  
  235.  
  236.